﻿using DynamicQuery.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Collections.Specialized;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace DynamicQuery.Test
{
    class StubValueProvider : IValueProvider
    {
        public StubValueProvider(NameValueCollection queryString, NameValueCollection form)
        {
            this.queryString = queryString;
            this.form = form;
        }

        NameValueCollection queryString, form;

        public bool ContainsPrefix(string prefix)
        {
            throw new NotImplementedException();
        }

        public ValueProviderResult GetValue(string key)
        {
            string value = queryString.Get(key);
            if (string.IsNullOrEmpty(value))
            {
                value = form.Get(key);
            }
            if (string.IsNullOrEmpty(value))
            {
                return null;
            }
            return new ValueProviderResult(attemptedValue: value, rawValue: null, culture: null);
        }
    }
    [TestClass]
    public class QueryDescriptorBinderTest
    {

        Mock<RequestContext> requestContextMoq = new Mock<RequestContext>();
        Mock<HttpContextBase> httpContextMoq = new Mock<HttpContextBase>();
        Mock<HttpRequestBase> httpRequestMoq = new Mock<HttpRequestBase>();
        Mock<ControllerBase> controllerBaseMoq = new Mock<ControllerBase>();
      
        ControllerContext controllerContext;

        [TestInitialize]
        public void InitMoq()
        {
            requestContextMoq.SetupGet(r => r.HttpContext).Returns(httpContextMoq.Object);
            httpContextMoq.SetupGet(h => h.Request).Returns(httpRequestMoq.Object);    
            controllerContext = new ControllerContext
            {
                RequestContext = requestContextMoq.Object,
                Controller = controllerBaseMoq.Object
            };
        }
         
        [TestMethod]
        public void TestMethod1()
        {
            NameValueCollection form = new NameValueCollection();
            form.Add("_query.Name", "test");
            form.Add("_query.Address.Province", "Jiangsu");
            form.Add("_query.Name.operator", QueryOperator.CONTAINS.ToString());
            form.Add("_query.Age", "10");
            form.Add("_query.Age.valuetype", "int");
            form.Add("_query.Age.operator", QueryOperator.GERATER.ToString());
            httpRequestMoq.SetupGet(h => h.Form).Returns(form);
            NameValueCollection queryString = new NameValueCollection();
            httpRequestMoq.SetupGet(h => h.QueryString).Returns(queryString);
            controllerBaseMoq.Object.ValueProvider = new StubValueProvider(queryString, form);
 
            QueryDescriptorBinder binder = new QueryDescriptorBinder();
            var descriptor= binder.BindModel(controllerContext, null) as QueryDescriptor;

            Assert.AreEqual(3, descriptor.Conditions.Count);
            Assert.AreEqual("Name", descriptor.Conditions[0].Key);
            Assert.AreEqual("Address.Province", descriptor.Conditions[1].Key);
            Assert.AreEqual("Age", descriptor.Conditions[2].Key);
            Assert.AreEqual(10, descriptor.Conditions[2].Value);
            Assert.AreEqual(QueryOperator.GERATER, descriptor.Conditions[2].Operator);
        }


        [TestMethod]
        public void TestMethod2()
        {
            NameValueCollection form = new NameValueCollection();
            form.Add("_query.Money", "11.11");
            form.Add("_query.Money.valuetype", "decimal");
            form.Add("_query.date", "2012-02-02");
            form.Add("_query.date.valuetype", "time");
            form.Add("_query.Money.operator", QueryOperator.LESSOREQUAL.ToString());
            httpRequestMoq.SetupGet(h => h.Form).Returns(form);
            NameValueCollection queryString = new NameValueCollection();
            queryString.Add("page", "2");
            queryString.Add("_query.pagesize", "15");
            queryString.Add("_query.orderbyasc", "Money");
            httpRequestMoq.SetupGet(h => h.QueryString).Returns(queryString);
            controllerBaseMoq.Object.ValueProvider = new StubValueProvider(queryString, form);

            QueryDescriptorBinder binder = new QueryDescriptorBinder();
            var descriptor = binder.BindModel(controllerContext, null) as QueryDescriptor;

            Assert.AreEqual(2, descriptor.Conditions.Count);

            Assert.AreEqual("Money", descriptor.Conditions[0].Key);
            Assert.AreEqual(11.11m, descriptor.Conditions[0].Value);
            Assert.AreEqual(QueryOperator.LESSOREQUAL, descriptor.Conditions[0].Operator);

            Assert.AreEqual("date", descriptor.Conditions[1].Key);           
            Assert.AreEqual(new DateTime(2012,2,2), descriptor.Conditions[1].Value);
            Assert.AreEqual(QueryOperator.EQUAL, descriptor.Conditions[1].Operator);

            Assert.AreEqual(2, descriptor.PageIndex);
            Assert.AreEqual(15, descriptor.PageSize);
            Assert.AreEqual(OrderSequence.ASC, descriptor.OrderBy.Order);
            Assert.AreEqual("Money", descriptor.OrderBy.Key);
        }
    }
}
